/* eslint-disable max-len */
import type { TreeProps } from 'ant-design-vue'
import { Input, Tree } from 'ant-design-vue'
import type { OnResize } from '@expresso/plus'
import { css } from '@emotion/css'
import { CaretDownOutlined } from '@ant-design/icons-vue'
import type { TreeDataMap } from './helper'
import { TREE_DATA, filterTreeData, formatTreeData } from './helper'
import { Page } from '@/components'

const ATreeDemo = defineComponent(() => {
  //# 成员

  const state: {
    treeData: TreeNode[]
    treeDataMap: TreeDataMap
  } = {
    treeDataMap: {
      pkey2children: {},
      key2node: {},
    },
    treeData: [],
  }

  //// 快速搜索 ////

  const searchText = ref<string>()

  const onSearch = () => {
    const text = searchText.value?.trim()
    if (!text) {
      tree.treeData = state.treeData
      tree.expandedKeys = []
    }
    else {
      const { treeData, expandedKeys } = filterTreeData(state.treeDataMap, (node) => {
        return (node.title as string).includes(text)
      })
      console.log('[onSearch]', treeData, expandedKeys)
      tree.treeData = treeData
      tree.expandedKeys = expandedKeys
    }
  }

  //// 树 ////

  const tree = shallowReactive<
    Omit<TreeProps, 'treeData'> & {
      treeData?: TreeNode[]
      onResize?: OnResize
    }
  >({
    treeData: [],

    onResize(data) {
      console.log('[onResize]', data.height)
      if (tree.height !== data.height) {
        tree.height = data.height
      }
    },
    onExpand(expandedKeys) {
      tree.expandedKeys = expandedKeys
    },

    onDragenter(info) {
      console.log('[onDragenter]', info)
    },
    onDragend(info) {
      console.log('[onDragend]', info)
    },
    onDragover(info) {
      console.log('[onDragover]', info)
    },
    onDragstart(info) {
      console.log('[onDragstart]', info)
    },
    onDrop(info) {
      // dropPosition
      // info.dragNode.pos
      console.log(
        '[onDrop]',
        `
        dragNode: { key: ${info.dragNode.key}, pos: ${(info.dragNode.pos ?? '').split('-').slice(-1)[0]} }, 
        dropNode: { key: ${info.node.key}, pos: ${info.dropPosition} }
        `,
        info,
      )

      //? dropPosition 索引位置
      //?
      //? [Node1]
      //?   │
      //?   ├(dropPosition) ([0])
      //?   │ ↗
      //?   ├[Node1-1]
      //?   │
      //?   ├(dropPosition) ([1])
      //?   │ ↗
      //?   ├[Node1-2]
      //?   │
      //?   ├(dropPosition) ([2])
      //?   │ ↗
      //?   ├[Node1-3]
      //?   │
      //?   ├(dropPosition) ([3])
      //?   │ ↗
      //?   ├[Node1-4]
      //?   │
      //?   ├(dropPosition) ([4])
      //?   │ ↗
      //?   ├[Node1-5]
      //?   │
      //?   └(dropPosition) (5)

      // console.log(
      //   '[onDrop]',
      //   `dropPosition： ${info.dropPosition}, dropToGap: ${info.dropToGap}, pos: ${info.node.pos}`,
      //   info,
      // )

      const { dragNode, /* dropNode, */ dropPosition } = info
      const dragIndex = (dragNode.dataRef?.pos ?? 0) as number
      // +((dragNode.pos ?? '').split('-').slice(-1)[0] ?? 0)
      const dropIndex = dropPosition
      const children = (dragNode.parent?.node as TreeNode)?.children ?? tree.treeData
      if (children) {
        const node = children![dragIndex]
        children![dragIndex] = null as any
        children!.splice(dropIndex, 0, node)
        let pos = 0
        const list = children.filter(item => (
          item ? (item.pos = pos++, 1) : 0
        ))
        children.length = 0
        children.push(...list)
        tree.treeData = [...tree.treeData!]
      }
    },
    allowDrop(info) {
      const { dragNode, dropNode, dropPosition } = info
      console.log('[allowDrop]', dragNode, dropNode, dropPosition)
      // console.log(
      //   '[allowDrop]',
      //   dragNode.pkey,
      //   dropNode.pkey,
      //   dragNode.key,
      //   dropNode.key,
      // )
      // return true
      return (
        (
          (
            dragNode.pkey === dropNode.pkey
            && dragNode.level === dropNode.level
            && dropPosition === 1
          )
          || dragNode.pkey === dropNode.key
        ) && Reflect.has(dropNode, 'pos')
      )
    },
  })

  //# 周期

  onMounted(() => {
    console.log('[onMounted]')
    const { treeData, treeDataMap } = formatTreeData(TREE_DATA)
    state.treeData = tree.treeData = treeData
    state.treeDataMap = treeDataMap
  })

  //# 渲染

  return () => (
    <Page contentClass={pageCSS}>
      <div class="quick-search">
        <Input
          v-model:value={searchText.value}
          placeholder="快速搜索"
          onInput={onSearch}
        />
      </div>

      <div class="tree" v-resize={tree.onResize}>
        <Tree
          height={tree.height}
          // defaultExpandAll
          expandedKeys={tree.expandedKeys}
          draggable
          blockNode
          showLine={{ showLeafIcon: false }}
          switcherIcon={(params: any) => {
            return <CaretDownOutlined class={params.switcherCls} />
          }}
          treeData={tree.treeData}
          allowDrop={tree.allowDrop}
          // onDragenter={tree.onDragenter}
          // onDragover={tree.onDragover}
          // onDragstart={tree.onDragstart}
          onDrop={tree.onDrop}
          // onDragend={tree.onDragend}
          onExpand={tree.onExpand}
        >
          {{
            title: ({ title }: { title: string }) => {
              const searchValue = searchText.value?.trim() ?? ''
              return (
                searchValue && (title.includes(searchValue))
                  ? (
                    <span>
                      { title.substring(0, title.indexOf(searchValue)) }
                      <span style="color: #f50">{ searchValue }</span>
                      { title.substring(title.indexOf(searchValue) + searchValue.length) }
                    </span>
                    )
                  : <span>{title}</span>
              )
            },
          }}
        </Tree>

      </div>

    </Page>
  )
})

//# 样式

const pageCSS = css`

  > .quick-search {
    padding: 8px;
    margin-bottom: 16px;
    background-color: #fff;
    border-radius: 6px;
  }

  > .tree {
    height: calc(100% - 48px - 16px);
    background-color: #fff;
    border-radius: 6px;
  }
`

export default ATreeDemo
